/**
 * Copyright (c) 2020 lizebang
 *
 * This software is released under the MIT License.
 * https://opensource.org/licenses/MIT
 */

package jiri

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"time"

	"go.fuchsia.dev/jiri/project"

	"gitee.com/banggua/ggtsync/config"
	"gitee.com/banggua/ggtsync/logger"
)

func projectsRemoteReplace(base string, projects project.Projects) error {
	for key, project := range projects {
		remote, err := projectRemoteURL(base, project.Remote)
		if err != nil {
			return err
		}
		project.Remote = remote
		projects[key] = project
	}
	return nil
}

func (jc *jiriClient) computeOps(cfgproj *config.Project) (func() error, map[string]operation, map[string]operation, error) {
	var (
		jirix       = jc.Xs[cfgproj.Name]
		cipddir     = cfgproj.Args["cipddir"]
		baseurl     = cfgproj.Args["baseurl"]
		manifestdir = cfgproj.Args["manifestdir"]
	)

	localProjectStates, err := loadProjectStates(cfgproj.To)
	if err != nil {
		return nil, nil, nil, err
	}
	localPackageStates, err := loadPackageStates(cipddir)
	if err != nil {
		return nil, nil, nil, err
	}

	fileInfos, err := ioutil.ReadDir("/tmp")
	if err != nil {
		logger.Errorf("%v %v", cfgproj, err)
		return nil, nil, nil, err
	}

	for _, fileInfo := range fileInfos {
		if strings.HasPrefix(fileInfo.Name(), "jiri") {
			err = os.RemoveAll(filepath.Join("/tmp", fileInfo.Name()))
			if err != nil {
				logger.Errorf("%v %v", cfgproj, err)
				return nil, nil, nil, err
			}
		}
	}

	loadProjects, err := project.LocalProjects(jirix, project.FullScan)
	if err != nil {
		logger.Errorf("%v %v", cfgproj, err)
		return nil, nil, nil, err
	}
	remoteProjects, remoteHooks, remotePackages, err := project.LoadUpdatedManifest(jirix, loadProjects, false)
	project.MatchLocalWithRemote(loadProjects, remoteProjects)
	if err != nil {
		logger.Errorf("%v %v", cfgproj, err)
		return nil, nil, nil, err
	}

	projectOps, err := computeProjects(cfgproj.To, localProjectStates, remoteProjects)
	if err != nil {
		return nil, nil, nil, err
	}
	packageOps := computePackages(cipddir, localPackageStates, remotePackages)

	err = projectsRemoteReplace(baseurl, remoteProjects)
	if err != nil {
		return nil, nil, nil, err
	}

	return func() error {
		manifest := &project.Manifest{}
		for _, remoteProject := range remoteProjects {
			manifest.Projects = append(manifest.Projects, remoteProject)
		}
		for _, remotePackage := range remotePackages {
			manifest.Packages = append(manifest.Packages, remotePackage)
		}
		for _, remoteHook := range remoteHooks {
			manifest.Hooks = append(manifest.Hooks, remoteHook)
		}
		manifest.ToFile(jirix, filepath.Join(manifestdir, cfgproj.Name+"-"+time.Now().In(time.FixedZone("CST", 8*3600)).Format("20060102")+".xml"))

		err := lockProjectStates(cfgproj.To, localProjectStates)
		if err != nil {
			logger.Errorf("%v %v", cfgproj, err)
			return err
		}
		err = lockPackageStates(cipddir, localPackageStates)
		if err != nil {
			logger.Errorf("%v %v", cfgproj, err)
			return err
		}
		return nil
	}, projectOps, packageOps, nil
}
